package com.gpj.learn.concurrent.jol.demo;

import com.gpj.learn.concurrent.jol.Example;
import lombok.extern.slf4j.Slf4j;
import org.openjdk.jol.info.ClassLayout;
import sun.misc.Unsafe;

import java.lang.reflect.Field;

/**
 * @className JolDemo2
 * @description
 *   非加锁时，对象头和hashcode的关系
 *   TODO
 *        在非加锁的情况下，一个对象创建出来的时候，对象头里边的并不存在实际的hashcode，
 *      当调用过hashcode方法之后，对象头中则存储对应的hashcode值
 * @author GPJ
 * @date 2020/6/15 8:38
 * @version 1.0
 **/
@Slf4j
public class JolDemo2 {
    public static void main(String[] args) {
        Example example = new Example();
        log.info("example的对象头为:{}", ClassLayout.parseInstance(example).toPrintable());
        log.info("通过java的方法得到的example的hashcode为:{}", Integer.toHexString(example.hashCode()));
        log.info("手动计算的example的hashcode为:{}", countHash(example));
        log.info("example的对象头为:{}", ClassLayout.parseInstance(example).toPrintable());
    }

    public static String countHash(Object object) {
        try {
            // 手动计算HashCode
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            Unsafe unsafe = (Unsafe) field.get(null);
            long hashCode = 0;
            for (long index = 7; index > 0; index--) {
                // 取Mark Word中的每一个Byte进行计算
                hashCode |= (unsafe.getByte(object, index) & 0xFF) << ((index - 1) * 8);
            }
            return Long.toHexString(hashCode);
        }catch (Exception e){
            return "";
        }
    }
}
